using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;

namespace Microsoft.Samples.Windows.Forms.Navigation
{
    /// <summary>
    /// A control that expects to be hosted in a navigation frame.
    /// </summary>
    /// <remarks>
    /// The Page class can store per-page information, and supplies default
    /// responses to navigation events. Also, as a shorthand, the class also forwards
    /// navigation commands on to the frame, avoiding the need to first obtain
    /// a reference to the frame.
    /// </remarks>
    public class Page : System.Windows.Forms.UserControl
    {
		/// <summary>
		/// Event fired when the frame is navigating into the page.
		/// </summary>
		[Category("Behavior")]
		[Description("Occurs when the frame is navigating into the page.")]
		public event PageEventHandler PageEnter = null;

		/// <summary>
		/// Event fired when the frame is navigating away from the page.
		/// </summary>
		[Category("Behavior")]
		[Description("Occurs when the frame is navigating away from the page.")]
		public event PageEventHandler PageLeave = null;

		/// <summary>
		/// Event fired when the value of the page's ScrollBars property changes.
		/// </summary>
		[Category("Property Changed")]
		[Description("Event fired when the value of ScrollBars property is changed on Control")]
		public event EventHandler ScrollBarsChanged = null;

    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.Container components = null;

		/// <summary>
		/// The frame containing this page.
		/// </summary>
		private Frame frame = null;

		/// <summary>
		/// Indicates whether the page wants scroll bars.
		/// </summary>
		private ScrollBars scrollBars = ScrollBars.Vertical;

    public Page()
    {
        InitializeComponent();
    }

		/// <summary>
		/// True if it is okay to navigate into this page using the given view state.
		/// </summary>
		/// <remarks>
		/// By default, this is always true. Page classes should override this
		/// property to perform custom validation to confirm it is okay to navigate
		/// into the page.
		/// </remarks>
		public virtual bool CanEnter(ViewState viewState)
		{
			return true;
		}
		
		/// <summary>
		/// True if it is okay to navigate away from this page.
		/// </summary>
		/// <remarks>
		/// By default, this is always true. Page classes should override this
		/// property to perform custom validation to confirm it is okay to navigate
		/// away from the page.
		/// </remarks>
		public virtual bool CanLeave()
		{
			return true;
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		/// <value>
		/// The parent of this page control, as a Frame object.
		/// </value>
		[Browsable(false)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public Frame Frame
		{
			get
			{
				return frame;
			}
			set
			{
				frame = value;
			}
		}
		
		/// <summary>
		/// Navigate to the specified page.
		/// </summary>
		/// <param name="page">The page to navigate to</param>
		public virtual void Go(Page page)
		{
			Frame.Go(page);
		}

		/// <summary>
		/// Navigate to a page of the specified type.
		/// </summary>
		/// <param name="pageType">The type of page to navigate to</param>
		public virtual void Go(Type pageType)
		{
			Frame.Go(pageType);
		}

		/// <summary>
		/// Navigate back one page.
		/// </summary>
		public void GoBack()
		{
			Frame.GoBack();
		}
		
		/// <summary>
		/// Go back n pages.
		/// </summary>
		/// <param name="n">The number of pages to go back</param>
		public void GoBack(int n)
		{
			Frame.GoBack(n);
		}
		
		/// <summary>
		/// Navigate forward one page.
		/// </summary>
		public void GoForward()
		{
			Frame.GoForward();
		}
		
		/// <summary>
		/// Go forward n pages.
		/// </summary>
		/// <param name="n">The number of pages to move forward</param>
		public void GoForward(int n)
		{
			Frame.GoForward(n);
		}
		
		/// <summary>
		/// Navigate to the home page.
		/// </summary>
		public void GoHome()
		{
			Frame.GoHome();
		}

		#region Designer generated code
		/// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
		{
			// 
			// Page
			// 
			this.BackColor = System.Drawing.SystemColors.Window;
			this.ForeColor = System.Drawing.SystemColors.WindowText;
			this.Name = "Page";
			this.Size = new System.Drawing.Size(300, 300);

		}
		#endregion

		/// <summary>
		/// Raise the ScrollBarsChanged event.
		/// </summary>
		protected virtual void OnScrollBarsChanged()
		{
			if (ScrollBarsChanged != null)
			{
				ScrollBarsChanged(this, EventArgs.Empty);
			}
		}

		/// <summary>
		/// Trigger the page's PageEnter event.
		/// </summary>
		/// <remarks>
		/// The frame calls this method whenever the user navigates to this page.
		/// Page classes should override this method to perform custom page setup,
		/// but should ensure that they call base.OnPageEnter() before any processing
		/// of their own.
		/// 
		/// The PageEventArgs's ViewState property can be used to reconstruct the
		/// state of this page from an earlier point in the navigation history.
		/// This parameter is null if the page has never been viewed before.
		/// </remarks>
		public virtual void OnPageEnter(PageEventArgs e)
		{
			if (e.ViewState != null)
			{
				/*
				 * This page has been visited before; read the earlier value
				 * of the page's Text property.
				 */
				Text = (string) e.ViewState.ReadProperty("Text");
			}

			if (PageEnter != null)
			{
				PageEnter(this, e);
			}
		}
		
		/// <summary>
		/// Trigger the page's PageLeave event.
		/// </summary>
		/// <remarks>
		/// The frame calls this method whenever it is navigating away from
		/// this page. By the time this method is called, the navigation cannot be
		/// cancelled. Page classes should override this method to perform custom
		/// page completion processing, but should ensure that they call
		/// base.OnPageLeave() before any processing of their own.
		/// 
		/// When the frame calls this method, it guarantees that the PageEventArgs's
		/// ViewState property is non-null. Pages can store information in this
		/// property that can later be used to reconstruct the state of the page
		/// at this point in the navigation history.
		/// </remarks>
		public virtual void OnPageLeave(PageEventArgs e)
		{
			// Remember the current value of the page's Text property.
			e.ViewState.WriteProperty("Text", Text);

			if (PageLeave != null)
			{
				PageLeave(this, e);
			}
		}
		
		/// <summary>
		/// Indicates whether the page wants horizontal and/or vertical scroll bars.
		/// </summary>
		/// <remarks>
		/// Setting this property fires the ScrollBarsChanged event.
		/// </remarks>
		[Category("Appearance")]
		[Description("Indicates whether the page wants its frame to give the page scroll bars.")]
		public ScrollBars ScrollBars
		{
			get
			{
				return scrollBars;
			}
			set
			{
				scrollBars = value;

				OnScrollBarsChanged();
			}
		}

		/// <summary>
		/// The text associated with the page. This is used as the page's title.
		/// </summary>
		/// <remarks>
		/// This overrides the base UserControl.Text property to ensure that the property
		/// is visible at design time in the Properties window.
		/// </remarks>
		[Browsable(true)]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		public override String Text
		{
			get
			{
				return base.Text;
			}
			set
			{
				base.Text = value;
			}
		}

		/// <returns>
		/// A textual representation of the page.
		/// </returns>
		public override string ToString()
		{
			return Text;
		}
	}
}
